#include <QDir>
#include <QInputDialog>
#include <QMessageBox>
#include "main_frame.h"
// models
#include <models/model_mesh.h>
// widgets
#include <widgets/mesh_widget.h>
#include <widgets/navigation_widget.h>
#include <widgets/palette_widget.h>
#include <widgets/surface_widget.h>
// presenters
#include <presenters/mesh_model_presenters.h>
#include <presenters/mesh_widget_presenters.h>
// model formats
#include <formats/mv.h>
#include <formats/gcad_multilayer.h>

using namespace boost;

namespace widgets {

MainFrame::MainFrame(QWidget *parent, Qt::WFlags flags)
  : QMainWindow(parent, flags),
  profile_dir_("profiles"),
  profile_name_(""),
  p_profile_menu_(0),
  p_profile_action_group_(new QActionGroup(this)),
  m_pModel(0),
  p_focused_widget_(0)
{
//  connect(p_app, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(on_focus_changed(QWidget*,QWidget*)));
//  ui.setupUi(this);
/*  p_environment_ = new Environment(mComponentFactory, menuBar(), this);
  QObject::connect(p_environment_, SIGNAL(widget_registered(const QString &)), this, SLOT(on_register_widget(const QString &)));
  p_environment_->register_actions(findChildren<QAction *>());
  { // profile selection menu generating
    p_profile_menu_ = new QMenu(tr("Select"));
    ui.menuProfile->insertMenu(ui.actionNew_profile, p_profile_menu_);
    refresh_profile_menu();
  }

  { // Panel menu
    typedef core::ComponentFactory::TWidgetFactory::TRegistryContainer TContainer;
    TContainer registry = mComponentFactory.mWidgetFactory.GetRegistry();

    for (TContainer::iterator it = registry.begin(); it != registry.end(); ++it)
    {
      QAction *p_action = ui.menuAdd_panel->addAction(it->first);
      p_action->setProperty("creator_id", it->first);
      QObject::connect(p_action, SIGNAL(triggered()), this, SLOT(on_make_dock()));
    }
  }
 
  load_preferences("SigmaViewer.ini");
  QWidget *p_central_widget = mComponentFactory.MakeWidget("Mesh");
  if (p_central_widget)
  {
    p_central_widget->setParent(this);
    p_central_widget->setFocusPolicy(Qt::ClickFocus);
    setCentralWidget(p_central_widget);
  }*/
}

MainFrame::~MainFrame()
{
  detach_model();
}

void MainFrame::select_profile(const QString &profile_name)
{
/*  if (!profile_name_.isEmpty()) // save previous profile if not empty
    save_profile(get_profile_path(profile_name_));
  profile_name_ = profile_name;
  { // load new profile
    load_profile(get_profile_path(profile_name));
    // save profile (create file if it's not exists) and refresh menu
    save_profile(get_profile_path(profile_name));
    refresh_profile_menu();
  }
  setWindowTitle(tr("SigmaViewer <%1>").arg(profile_name_));*/
}

void MainFrame::attach_model(QObject *_pModel)
{
/*  models::Mesh_model *pMeshModel = qobject_cast<models::Mesh_model *>(_pModel);

  detach_model();
// attach docking widgets presenter
  foreach(DockWidget *pDockWidget, findChildren<DockWidget *>())
  {
    QWidget *pWidget = pDockWidget->widget();
    mComponentFactory.mPresenterFactory.Attach(_pModel, pWidget);
  }
// attach central widget presenter
  {
    QWidget *p_central_widget = centralWidget();
    if (p_central_widget)
      mComponentFactory.mPresenterFactory.Attach(_pModel, p_central_widget);
  }

  mComponentFactory.mPresenterFactory.Attach(_pModel, p_environment_);
  m_pModel = _pModel;*/
}

void MainFrame::on_vertex_action()
{
/*  QAction *p_action = (QAction *) sender();
  
  widgets::MeshWidget *p_widget = qobject_cast<widgets::MeshWidget *>(p_focused_widget_);
  
  if (p_widget == 0)
    return;
  
//  presenters::mesh_widget:: qVariantValue(p_widget->property("mvp::presenter"));
  using namespace presenters::mesh_model;

  Mesh_widget_presenter *pPresenter = mvp::GetViewPresenter<Mesh_widget_presenter *>(p_widget);

  pPresenter->mModelWrapper.mFieldName = p_action->text();*/
}

void MainFrame::detach_model()
{
  if (m_pModel)
  {
    m_pModel->deleteLater();
    m_pModel = 0;
  }
}

// privates
void MainFrame::load_preferences(const QString &file_name)
{
/*  QSettings settings(file_name, QSettings::IniFormat);
  settings.beginGroup("mainframe");
  restoreGeometry(settings.value("geometry").toByteArray());
  QString profile_name = settings.value("profile_name", "default").toString();
  settings.endGroup();
  select_profile(profile_name);
  p_environment_->load_preferences(settings);*/
}

void MainFrame::save_preferences(const QString &file_name)
{
/*  QSettings settings(file_name, QSettings::IniFormat);
  settings.clear();
  settings.beginGroup("mainframe");
  settings.setValue("geometry", saveGeometry());
  settings.setValue("profile_name", profile_name_);
  settings.endGroup();
  if (!profile_name_.isEmpty())
    save_profile(get_profile_path(profile_name_));
  p_environment_->save_preferences(settings);*/
}

void MainFrame::save_profile(const QString &file_name)
{
/*  QSettings settings(get_profile_path(profile_name_), QSettings::IniFormat);
  settings.clear();
  settings.beginGroup("profile");
  { // store dock widgets
    int ind_dock = 0;
    foreach(DockWidget *p_DockWidget, findChildren<DockWidget *>())
    {
      settings.beginGroup(QString("dock%1").arg(++ind_dock));
      QWidget *p_widget = p_DockWidget->widget();
      QString creator_id = p_widget->property("creator_id").toString();
      settings.setValue("creator_id", creator_id);
      settings.setValue("title", p_DockWidget->windowTitle());
      settings.setValue("dock_uuid", p_DockWidget->objectName());
      settings.endGroup();
    }
    settings.setValue("dock_qty", ind_dock);
  }
  settings.setValue("dock_state", saveState());
  settings.endGroup();
  p_environment_->save_profile(settings);*/
}

void MainFrame::load_profile(const QString &file_name)
{
/*  QSettings settings(file_name, QSettings::IniFormat);
  foreach(DockWidget *p_DockWidget, findChildren<DockWidget *>())
    p_DockWidget->deleteLater();

  settings.beginGroup("profile");
  { // restore dock widgets
    const int dock_qty = settings.value("dock_qty").toInt();
    for (int ind_dock = 1; ind_dock <= dock_qty; ++ind_dock)
    {
      settings.beginGroup(QString("dock%1").arg(ind_dock));
      const QString creator_id = settings.value("creator_id").toString();
      const QString title = settings.value("title").toString();
      const QString dock_uuid = settings.value("dock_uuid").toString();

      QWidget *p_widget =  mComponentFactory.MakeWidget(creator_id);
      if (p_widget)
        make_dock(p_widget, title, creator_id, dock_uuid);
      settings.endGroup();
    }
  }
  restoreState(settings.value("dock_state").toByteArray());
  settings.endGroup();
  p_environment_->load_profile(settings);*/
}

QString MainFrame::get_profile_path(const QString &profile_name) const
{
  return profile_dir_ + "/" + profile_name + ".ini";
}

void MainFrame::refresh_profile_menu()
{
  QDir dir(profile_dir_);
  p_profile_menu_->clear();
  foreach(QFileInfo info, dir.entryInfoList(QStringList("*.ini")))
  {
    QAction *p_select_profile_action = p_profile_menu_->addAction(info.baseName());
    p_profile_action_group_->addAction(p_select_profile_action);
    p_select_profile_action->setCheckable(true);
    p_select_profile_action->setChecked(profile_name_ == p_select_profile_action->text());
    connect(p_select_profile_action, SIGNAL(triggered()), this, SLOT(on_actionSelect_profile()));
  }
}

DockWidget *MainFrame::make_dock(const QString &creator_id)
{
/*  bool is_ok = false;
  QString title = QInputDialog::getText(this, tr("creating panel"), tr("Input panel title: "), QLineEdit::Normal, "", &is_ok);
  if (is_ok)
  {
    QWidget *p_widget = mComponentFactory.MakeWidget(creator_id);
    if (p_widget)
      return make_dock(p_widget, title, creator_id, QUuid::createUuid());
  }*/
  return 0;
}

DockWidget *MainFrame::make_dock(QWidget *p_widget, const QString &title, const QString &creator_id, const QString &dock_uuid)
{
/*  p_widget->setProperty("creator_id", creator_id);
  p_widget->setParent(this);

  DockWidget *p_DockWidget = new DockWidget(title, this);
  p_DockWidget->setWidget(p_widget);
  connect(p_DockWidget, SIGNAL(closed(DockWidget *)), SLOT(on_close_dock(DockWidget *)));
  p_DockWidget->setObjectName(dock_uuid);
  addDockWidget(Qt::LeftDockWidgetArea, p_DockWidget);
  mComponentFactory.mPresenterFactory.Attach(m_pModel, p_widget);
  mComponentFactory.mPresenterFactory.Attach(p_widget, p_environment_);
  p_widget->setFocusPolicy(Qt::ClickFocus);

  return p_DockWidget;*/
  return 0;
}

void MainFrame::closeEvent(QCloseEvent *p_event)
{
  save_profile(get_profile_path(profile_name_));
  save_preferences("SigmaViewer.ini");
}

void MainFrame::on_focus_changed(QWidget *p_old, QWidget *p_new)
{
  p_focused_widget_ = p_new;
/*  if (p_focused_widget_presenter_wrapper_)
  {
    delete p_focused_widget_presenter_wrapper_;
    p_focused_widget_presenter_wrapper_ = 0;
  }
  if (p_new)
    p_focused_widget_presenter_wrapper_ = p_environment_->attach_presenter(p_new, &action_registry_);*/
}

void MainFrame::on_actionSelect_profile()
{
  QAction *p_action = qobject_cast<QAction *>(sender());
  select_profile(p_action->text());
}

void MainFrame::on_actionAbout_triggered()
{
//  QMessageBox::about(this, tr("About"), revision + "\n\n" + authors);
}

void MainFrame::on_actionToggle_fullscreen_triggered()
{
  setWindowState(windowState() ^ Qt::WindowFullScreen);
}

void MainFrame::on_actionNew_profile_triggered()
{
  bool is_ok = false;
  QString profile_name = QInputDialog::getText(this, tr("create new profile"), tr("profile name"), QLineEdit::Normal, "", &is_ok);
  if (is_ok && !profile_name.isEmpty())
    select_profile(profile_name);
}

void MainFrame::on_make_dock()
{
  make_dock(sender()->property("creator_id").toString());
}

void MainFrame::on_close_dock(DockWidget *p_DockWidget)
{
  p_DockWidget->deleteLater();
}

void MainFrame::on_register_widget(const QString &name)
{
  QAction *p_action = ui.menuAdd_panel->addAction(name);
  p_action->setProperty("creator_id", name);
  QObject::connect(p_action, SIGNAL(triggered()), this, SLOT(on_make_dock()));
}

void MainFrame::on_actionOpen_triggered()
{
/*  QObject *p_model = p_environment_->open_model();
  if (p_model)
    attach_model(p_model);*/
}

void MainFrame::on_actionToggle_wireframe_triggered()
{
/*  widgets::MeshWidget *p_mesh_widget = qobject_cast<widgets::MeshWidget *>(p_focused_widget_);

  if (p_mesh_widget != NULL)
    p_mesh_widget->set_wireframe(!p_mesh_widget->get_wireframe());*/
}

} // namespace ui